/**
 * Created with IntelliJ IDEA.
 * Description:二叉搜索树的模拟实现
 * User: dings
 * Date: 2024-08-18
 * Time: 20:42
 */
public class SearchTree {
    TreeNode root;
    static class TreeNode {
        //左右孩子表示法
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }
    }

    /**
     * 数据插入
     * @param val
     */
    public void insert(int val) {
        TreeNode node = new TreeNode(val);
        if (root == null) {
            root = node;
            return;
        }
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if (val > cur.val) {
                parent = cur;
                cur = cur.right;
            }else if (val < cur.val) {
                parent = cur;
                cur = cur.left;
            }else {
                //二叉搜索树中节点的值不能重复
                return;
            }
            if (val > parent.val) {
                parent.right = node;
            }else {
                parent.left = node;
            }
        }
    }

    /**
     * 查找数据
     * @param val
     * @return
     */
    public TreeNode searchNode(int val) {
        TreeNode cur = root;
        while (cur != null) {
            if (val > cur.val) {
                cur = cur.right;
            }else if (val < cur.val) {
                cur = cur.left;
            }else {
                return cur;
            }
        }
        return null;
    }

    /**
     * 删除数据
     * @param val
     * @return
     */
    public boolean removeNode(int val) {
        TreeNode cur = root;
        TreeNode parent = null;
        //找到要删除的节点cur和其父节点parent的位置
        while (cur != null) {
            if (val > cur.val) {
                parent = cur;
                cur = cur.right;
            }else if (val < cur.val) {
                parent = cur;
                cur = cur.left;
            }else {
                break;
            }
        }
        //没有该节点
        if (cur == null) {
            return false;
        }
        if (cur != root) {
            //cur不为根节点
            if (cur == parent.right) {
                //cur为父节点的左孩子
                if (cur.left == null) {
                    //cur左树为空
                    parent.right = cur.right;
                }else if (cur.right == null){
                    //cur右树为空
                    parent.right = cur.left;
                }else {
                    //左右都不为空
                    removeSub(cur);
                }
                return true;
            }else {
                //cur为父节点的右孩子
                if (cur.left == null) {
                    //cur左树为空
                    parent.left = cur.right;
                }else if (cur.right == null){
                    //cur右树为空
                    parent.left = cur.left;
                }else {
                    //左右都不为空
                    removeSub(cur);
                }
                return true;
            }
        }else {
            //cur为根节点
            if (cur.left == null) {
                //cur左树为空
                root = cur.right;
            }else if (cur.right == null) {
                //cur右树为空
                root = cur.left;
            }else {
                //左右都不为空
                removeSub(cur);
            }
            return true;
        }
    }

    private void removeSub(TreeNode cur) {
        //将要删除节点的值更改为其左树中值最大的节点（左树中最右边的节点）或者右树中值最小的节点（右树中最左边的节点），并删除这个节点
        //这样可以使其仍满足二叉搜索树的特征：左 < 根 < 右
        //这里更改为左树中的值最大的节点
        TreeNode rParent = cur.left;
        TreeNode right = rParent.right;
        if (right != null) {
            while (right.right != null) {
                rParent = right;
                right = right.right;
            }
            cur.val = right.val;
            rParent.right = right.left;
        }else {
            //当cur的左孩子就是左子树中的最大值时
            cur.val = rParent.val;
            cur.left = rParent.left;
        }
    }
}
